package laberinto;
import fantasma.Fantasmas;
import interfaces.IFantasma;
import interfaces.ILaberinto;
import interfaces.IObjetoComible;
import interfaces.IObservador;

import java.util.ArrayList;
import java.util.HashMap;

import utilidades.Constantes;
import utilidades.Vector;


public class Laberinto implements ILaberinto{
	
	private int cantidadFilas;
	private int cantidadColumnas;

	private Casilla CasillaInicialPacman;
	private Casilla CasillaInicialFantasmas;
	private ArrayList<Bolon> bolones;
	private ArrayList<Bolita> bolitas;
	
	HashMap<String, Casilla> laberinto;
	private Fantasmas fantasmas = new Fantasmas();
	private ArrayList<IObservador> observadores = new ArrayList<IObservador>();
	private int cantidadDeComibles = 0;
	private String id;
	
	@Override
	public Fantasmas obtenerFantasmas() {
		return fantasmas;
	}
	
	@Override
	public void agregarFantasmas(IFantasma fantasma){
		fantasmas.agregar(fantasma,this.obtenerCasillaInicialFantasmas());
	}

	@Override
	public void agregarFantasmas(IFantasma fantasma,int delta){
		Casilla casilla = this.obtenerCasillaInicialFantasmas();
		int fil = casilla.obtenerFila();
		int col = casilla.obtenerColumna();
		
		if(delta>0)
			casilla = obtenerCasillaPorId(String.valueOf(fil+delta)+String.valueOf(col));
		else
			casilla = obtenerCasillaPorId(String.valueOf(fil)+String.valueOf(col+delta));
		fantasmas.agregar(fantasma,casilla);
	}
	
	
	
	/**
	 * @param cantidadFilas
	 * @param cantidadColumnas
	 * @param casillaInicialPacman
	 * @param casillaInicialFantasmas
	 * @param bolones
	 * @param laberinto
	 * @param fantasmas
	 */
	public Laberinto(int cantidadFilas, int cantidadColumnas,
			Casilla casillaInicialPacman, Casilla casillaInicialFantasmas,
			ArrayList<Bolon> bolones, HashMap<String, Casilla> laberinto,
			Fantasmas fantasmas) {
		super();
		this.cantidadFilas = cantidadFilas;
		this.cantidadColumnas = cantidadColumnas;
		CasillaInicialPacman = casillaInicialPacman;
		CasillaInicialFantasmas = casillaInicialFantasmas;
		this.bolones = bolones;
		this.laberinto = laberinto;
		this.fantasmas = fantasmas;
	}

	public Laberinto(String id){
		laberinto = new HashMap<String, Casilla>();
		bolones = new ArrayList<Bolon>();
		bolitas = new ArrayList<Bolita>();
		this.id=id;
	}
	
	public Laberinto(){
		laberinto = new HashMap<String, Casilla>();
		bolones = new ArrayList<Bolon>(); 
		this.id=" ";
	}
	
	public Laberinto(int cantidadFilasLaberinto, int cantidadColumnasLaberinto,
			String casillaInicialPacman, String casillaInicialFantasmas) {
		laberinto = new HashMap<String, Casilla>();
		bolones = new ArrayList<Bolon>(); 
		this.cantidadFilas = cantidadFilasLaberinto;
		this.cantidadColumnas = cantidadColumnasLaberinto;
		cambiarCasillaInicialPacman(casillaInicialPacman);
		cambiarCasillaInicialFantasmas(casillaInicialFantasmas);
	}

	public void agregarBolonALaberinto(Bolon nuevoBolon){
		bolones.add(nuevoBolon);
	}
	
	public void cambiarCantidadFilas(int cantidad) {
		cantidadFilas = cantidad;
	}

	public void cambiarCantidadColumnas(int cantidad) {
		cantidadColumnas = cantidad;
	}

	public void cambiarCasillaInicialPacman(String idCasilla) {
		CasillaInicialPacman = this.obtenerCasillaPorId(idCasilla);
		if (CasillaInicialPacman == null)
				CasillaInicialPacman = new NullCasilla();
	}

	public void cambiarCasillaInicialFantasmas(String idCasilla) {
		CasillaInicialFantasmas = this.obtenerCasillaPorId(idCasilla);
		if (CasillaInicialFantasmas == null)
			CasillaInicialFantasmas = new NullCasilla();
	}

	public int obtenerCantidadFilas() {
		return cantidadFilas;
	}

	public int obtenerCantidadColumnas() {
		return cantidadColumnas;
	}

	public Casilla obtenerCasillaInicialPacman() {
		if(Constantes.MODO_DEBUG)
			System.out.println("obtiene casilla inicial del pacman con un laberinto de cantidadDeBolitas:"+bolitas.size()+"(nivel"+id+")");		
		return CasillaInicialPacman;
	}

	public Casilla obtenerCasillaInicialFantasmas() {
		return CasillaInicialFantasmas;
	}

	public HashMap<String, Casilla> getLaberinto(){
		return laberinto;
	}
	
	public void agregarCasilla(Casilla casillaNueva) {
		laberinto.put(casillaNueva.obtenerIdCasilla(), casillaNueva);
	}
	
	@Override
	public void sacarContenidoDeCasilla(IObjetoComible oComible,String idCasilla){
		Casilla casilla = laberinto.get(idCasilla);
		if (casilla.esOcupable()){
			casilla.sacarContenido(oComible);
		}
		bolitas.remove(oComible);

		/*if(cantidadDeComibles==0){
			notificarCambios();
		}*/
		
		if(Constantes.MODO_DEBUG){
			if(bolitas.size()<0)
				System.out.println("cantidad De Bolitas:"+bolitas.size()+"?");
			System.out.println("cantidad De Bolitas:"+bolitas.size()+" de nivel"+id);
		}
	}
	
	@Override
	public boolean tieneBolitas(){
		return bolitas.size()>0;
	}
	

	@Override
	public void agregarContenidoDeCasilla(IObjetoComible oComible,String idCasilla){
		Casilla casilla = laberinto.get(idCasilla);
		if (casilla != null){
			casilla.agregarContenido(oComible);
		cantidadDeComibles++;
		}
		
		if(Constantes.MODO_DEBUG)
			System.out.println("cantidadDeComibles agregados:"+cantidadDeComibles+" en nivel"+id);

	}
	
	public Casilla obtenerCasillaPorId(String idCasilla) {
		Casilla casillaAuxiliar = laberinto.get(idCasilla);
		if (casillaAuxiliar == null)
			casillaAuxiliar = new NullCasilla();
		return casillaAuxiliar;
	}

	public ArrayList<Vector> obtenerDireccionesPosibles(Casilla casillaFantasma){
		return casillaFantasma.obtenerDireccionesPosibles();
	}
	
	public ArrayList<Bolon> ObtenerBolones(){
		return bolones;
	}

	@Override
	public void cambiarFantasmas(Fantasmas fantasmas) {
		this.fantasmas = fantasmas;
	}

	@Override
	public void agregar(IObservador observador) {
		observadores.add(observador);
	}

	@Override
	public void eliminar(IObservador observador) {
		observadores.remove(observador);
	}

	@Override
	public void agregar(ArrayList<IObservador> observadores) {
		this.observadores.addAll(observadores);
	}
		
	@Override
	public void notificarCambios() {
		for (IObservador observador : observadores) {
			observador.actualizar();
		}
	}

	@Override
	public void agregarObservador(IObservador observador) {
		this.observadores.add(observador);
	}

	@Override
	public ArrayList<Bolita> ObtenerBolitas() {
		return bolitas;
	}

	@Override
	public void agregarBolitaALaberinto(Bolita bolita) {
		bolitas.add(bolita);
	}	
	
}
